package com.ete.service.service.location.android

import android.Manifest
import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.location.Location
import android.location.LocationListener
import android.os.Build
import android.os.Looper
import android.provider.Settings
import com.blankj.utilcode.util.PermissionUtils
import com.blankj.utilcode.util.PermissionUtils.SimpleCallback
import com.blankj.utilcode.util.Utils
import com.ete.service.entry.location.LocationEntry
import com.ete.service.entry.location.LocationResult
import com.ete.service.manager.ManagerConstant
import com.ete.service.manager.location.LocationManager
import com.ete.service.service.R
import com.ete.service.service.location.ILocationListener
import com.ete.service.util.log.EteLog
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext


/**
 * Author:LiXian
 * <p>
 * Desc:安卓原始api定位
 * Version:1.0
 * date 2025/4/21 11:32
 */
class AndroidApiLocation : ILocationListener() {

    private var isLocation = false
    private var mLocationCount: Int = 0
    private var mLocationJob: Job? = null
    private var mManager: android.location.LocationManager? = null

    private var mLocationEntry: LocationEntry? = null

    private var mLocationResult: LocationResult? = null

    private val mPermissions: Array<String> = arrayOf(
            Manifest.permission.ACCESS_COARSE_LOCATION,
            Manifest.permission.ACCESS_FINE_LOCATION,
            Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS
    )

    override fun initLocation(mEntry: LocationEntry) {
        EteLog.d(LocationManager.TAG_ANDROID_API, "初始化AndroidApi定位")
        mLocationEntry = mEntry
        mLocationCount = 0
        val manager = Utils.getApp().getSystemService(Context.LOCATION_SERVICE)
        if (manager is android.location.LocationManager) mManager = manager
    }

    override fun checkedPermission(mCallback: (Int) -> Unit) {
        super.checkedPermission(mCallback)
        val mCode = isCheckLocation()
        when (mCode) {
            ManagerConstant.CODE_NOT_PERMISSION -> applyPermission(mCallback)
            else -> mCallback.invoke(mCode)
        }
    }

    override fun startLocation(): Int {
        EteLog.d(LocationManager.TAG_ANDROID_API, "开始定位")
        if (mManager == null || mLocationEntry == null) {
            initLocation(LocationEntry())
        }
        val mCode = isCheckLocation()
        if (mCode != ManagerConstant.CODE_SUCCESS) return mCode
        startLocationJob()
        return ManagerConstant.CODE_SUCCESS
    }

    override fun isLocationning(): Boolean {
        return isLocation
    }

    override fun stopLocation() {
        mManager?.removeUpdates(mListener)
        cancelJob()
    }

    override fun destroyLocation() {
        stopLocation()
        mLocationCount = 0
        mManager = null
        mLocationEntry?.mCallback = null
        mLocationEntry = null
    }

    override fun getLocationResult(): LocationResult? {
        return mLocationResult
    }

    @SuppressLint("MissingPermission")
    private fun startLocationJob() {
        cancelJob()
        isLocation = true
        EteLog.d(LocationManager.TAG_ANDROID_API, "开始定位任务")
        mLocationJob = CoroutineScope(Dispatchers.IO).launch {
            val interval = (mLocationEntry?.interval ?: 30) * 1000L
            val maxCount = (mLocationEntry?.maxLocationCount ?: 60)
            while (isLocation) {
                mLocationCount++
                val mLocation = mManager?.getLastKnownLocation(android.location.LocationManager.GPS_PROVIDER)
                if (mLocation != null) {
                    EteLog.d(LocationManager.TAG_ANDROID_API, "最后一次定位信息不为空，直接返回定位结果")
                    callResult(mLocation)
                } else {
                    requestLocationUpdates()
                }
                if (mLocationCount > maxCount) {
                    stopLocation()
                } else {
                    delay(interval)
                }
            }
        }
    }

    private val mListener: LocationListener = LocationListener { location -> callResult(location) }

    @SuppressLint("MissingPermission")
    private suspend fun requestLocationUpdates() {
        withContext(Dispatchers.Main) {
            try {
                mManager?.requestLocationUpdates(
                        android.location.LocationManager.GPS_PROVIDER,
                        1000L,
                        1F,
                        mListener,
                        Looper.getMainLooper()
                )
            } catch (ex: Exception) {
                EteLog.d(LocationManager.TAG_ANDROID_API, "请求定位异常ex:[$ex]")
            }
        }
    }

    private fun callResult(mLocation: Location) {
        EteLog.d(LocationManager.TAG_ANDROID_API, "返回AndroidApi定位结果mLocation:[$mLocation]")
        val mResult = LocationResult()
        mResult.count = mLocationCount
        mResult.code = ManagerConstant.CODE_SUCCESS
        mResult.result = Utils.getApp().getString(R.string.location_success)
        mResult.latitude = mLocation.latitude
        mResult.longitude = mLocation.longitude
        mResult.altitude = mLocation.altitude
        mResult.accuracy = mLocation.accuracy
        mResult.time = mLocation.time
        mLocationResult = mResult
        if (mLocationEntry?.isInterval != true) stopLocation()
        mLocationEntry?.mCallback?.invoke(mResult)
    }

    private fun cancelJob() {
        EteLog.d(LocationManager.TAG_ANDROID_API, "取消定位任务")
        isLocation = false
        mLocationJob?.cancel()
        mLocationJob = null
    }

    /**
     * 检测定位权限
     */
    private fun isCheckLocation(): Int {
        if (mLocationEntry == null || mManager == null) {
            EteLog.d(LocationManager.TAG_ANDROID_API, "未初始化")
            return ManagerConstant.CODE_NOT_INIT
        }
        if (!mManager!!.isProviderEnabled(android.location.LocationManager.GPS_PROVIDER)) {
            EteLog.d(LocationManager.TAG_ANDROID_API, "GSP定位不可用")
            return ManagerConstant.CODE_GPS_UNENABLED
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P && !mManager!!.isLocationEnabled) {
            EteLog.d(LocationManager.TAG_ANDROID_API, "定位功能不可用")
            return ManagerConstant.CODE_NOT_SUPPORT_LOCATION
        }
        val isGranted = PermissionUtils.isGranted(*mPermissions)
        if (!isGranted) {
            EteLog.d(LocationManager.TAG, "权限检测不通过")
            return ManagerConstant.CODE_NOT_PERMISSION
        }
        return ManagerConstant.CODE_SUCCESS
    }

    /**
     * 跳转打开GPS
     */
    override fun navigationOpenGps() {
        // 跳转到 GPS 设置界面（无 Activity 时需要 FLAG_ACTIVITY_NEW_TASK）
        val intent = Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        Utils.getApp().startActivity(intent)
    }

    /**
     * 申请权限
     */
    private fun applyPermission(mCallback: (Int) -> Unit) {
        PermissionUtils.permission(*mPermissions).callback(object : SimpleCallback {
            override fun onGranted() {
                checkedPermission(mCallback)
            }

            override fun onDenied() {
                mCallback.invoke(ManagerConstant.CODE_NOT_PERMISSION)
            }

        }).request()
    }
}